package com.drool.mediaplayer.services;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.drool.mediaplayer.MediaPlayerActivity;
import com.drool.mediaplayer.MyPreferences;
import com.drool.mediaplayer.Playlist;
//import com.drool.mediaplayer.PlaylistException;
import com.drool.mediaplayer.R;
import com.drool.mediaplayer.Interfaces.INowPlayingCallback;
import com.drool.mediaplayer.Interfaces.IRemoteCallback;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.drawable.BitmapDrawable;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.net.Uri.Builder;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.MediaStore.Audio;
import android.util.Log;
import android.widget.TextView;
import android.widget.VideoView;

public class DroolService extends Service {

	private MediaPlayer mp = null;
	private int bufferPercentage = 0;
	private Uri myMedia = null;
	private String Id = "-1";
	private String albumId = "-1";
	private String SongName, AlbumName, Artist;
	
	private static final String TAG = "DroolService";
	private IRemoteCallback callback = null;
	private INowPlayingCallback npCallback = null;
	private Thread syncThread = null;
	
	private NotificationManager notifier = null;
	private Notification notify = null;
	private List<String> playlistItems;
	
	private int currentSongIndex; //the list index of the curretn song
	private String playlistController;
	
	public static final int PLAYLIST_SHUFFLE_ON = 1;
	public static final int PLAYLIST_SHUFFLE_OFF = 0;
	public static final int PLAYLIST_LOOP_ON = 1;
	public static final int PLAYLIST_LOOP_OFF = 0;
	private int shuffleState = PLAYLIST_SHUFFLE_OFF, loopState = PLAYLIST_LOOP_OFF;
	
	public static final String PLAYLIST_CONTROLLER_GUI = "gui";
	public static final String PLAYLIST_CONTROLLER_SERVICE = "service";
	
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		
		Log.i(TAG, IRemoteInterface.class.getName());
		return mBinder;
	}

	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		
		notifier = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
		notify = new Notification();
		
		playlistItems = new ArrayList<String> ();
		
		if (mp == null){
			Log.i(TAG, "Creating new MediaPLayer");			
			mp = new MediaPlayer();
			mp.setOnBufferingUpdateListener(new OnBufferingUpdateListener(){

				@Override
				public void onBufferingUpdate(MediaPlayer arg0, int percentage) {
					// TODO Auto-generated method stub
					bufferPercentage = percentage;
					Log.i(TAG, "buffer perc" + Integer.toString(bufferPercentage));
				}
				
			});

			mp.setOnCompletionListener(new OnCompletionListener() {

				@Override
				public void onCompletion(MediaPlayer mp) {
					// TODO Auto-generated method stub
					try {
						if (playlistController.equals(PLAYLIST_CONTROLLER_GUI)){
							Log.i(TAG, "Callback called");
							callback.playbackComplete();
						}
						else{
							Log.i(TAG, "not calling GUI callback");
							String song = null;
							try {
								//song = pl.getNextSong();
								//use the playlistItems list to get the next song
								
								//int i = playlistItems.indexOf(currentSongId);
								int i = currentSongIndex;
								Log.i(TAG, "Current song " + Integer.toString(i));
								i++;
								//*** Change i++ to getNextSong() by mimicing eveythig hat
								// the playlist class does
								//i = getNextSong();
								if (i <= playlistItems.size()-1){
									Log.i(TAG, "Next song " + Integer.toString(i));
									mBinder.setId(playlistItems.get(i), "");
									currentSongIndex = i;
									Log.i(TAG, "Current song set to" + currentSongIndex);
									//updateNumTimesPlayed(song, "Audio");
									
									mBinder.prepareForPlay();
	
									mBinder.play();
								}
								
							} catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}

						}
							
					} catch (RemoteException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				
			});

		}
		
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		notifier.cancel(1);
		mp.stop();
		mp=null;
	}

	@Override
	public void onStart(Intent intent, int startId) {
		// TODO Auto-generated method stub
		super.onStart(intent, startId);	
	}

	@Override
	public boolean onUnbind(Intent intent) {
		// TODO Auto-generated method stub
		return super.onUnbind(intent);
	}
	
	private final IRemoteInterface.Stub mBinder = new IRemoteInterface.Stub() {
		
		@Override
		public void setId(String currentId, String aId) throws RemoteException {
			// TODO Auto-generated method stub
			Id = currentId;
			ContentResolver resolver = getContentResolver();
			
			Cursor audioCursor = resolver.query(Audio.Media.EXTERNAL_CONTENT_URI, new String [] {
					Audio.Media._ID, Audio.Media.ALBUM_ID}
			,Audio.Media._ID + "="+ Id,null, null);	
			
			if (audioCursor.getCount()>0){
				audioCursor.moveToFirst();
				albumId = audioCursor.getString(1);
			}else
				albumId = null;
			
			Log.i(TAG, "albumid " + albumId);
			audioCursor.close();
		}

		@Override
		public String getId() throws RemoteException {
			// TODO Auto-generated method stub
			return Id;
		}

		@Override
		public void prepareForPlay() throws RemoteException {
			// TODO Auto-generated method stub
			try {		
				if (mp.isPlaying()){
					mp.stop();
				}
				
				mp.reset();				
				Builder uBuilder = Audio.Media.EXTERNAL_CONTENT_URI.buildUpon();
				
				myMedia = uBuilder.appendPath(Id).build();
				
				mp.setDataSource(DroolService.this, myMedia);
				mp.prepare();
				
				Uri audio = Audio.Media.EXTERNAL_CONTENT_URI;
				Uri album = Audio.Albums.EXTERNAL_CONTENT_URI;
				
				ContentResolver resolver = getContentResolver();
				
				Cursor audioCursor = resolver.query(audio, new String [] {
						Audio.Media._ID, Audio.Media.ARTIST, Audio.Media.TITLE, Audio.Media.ALBUM_ID}
				,Audio.Media._ID + "="+ Id,null, null);
				
				
				if (audioCursor.getCount() > 0){
					audioCursor.moveToFirst();
					Artist = audioCursor.getString(1);
					SongName = audioCursor.getString(2);
					
					Cursor albumCursor = resolver.query(album, new String[] {
							Audio.Albums._ID, Audio.Albums.ALBUM, Audio.Albums.ALBUM_ART},
							Audio.Albums._ID + "=" + audioCursor.getString(3), null, null);
					if (albumCursor.getCount()>0){
						albumCursor.moveToFirst();
						AlbumName = albumCursor.getString(1);
					}
					else
						AlbumName = "Unknown";
					
				}
				else {
					Artist = "Artist Unknown";
					SongName = "Unknown";
				}	
			
				
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		@Override
		public int getPosition() throws RemoteException {
			// TODO Auto-generated method stub
			return mp.getCurrentPosition();
		}

		@Override
		public int getSongDuration() throws RemoteException {
			// TODO Auto-generated method stub
			return mp.getDuration();
		}

		@Override
		public void registerCallback(IRemoteCallback cb) throws RemoteException {
			// TODO Auto-generated method stub
			Log.i(TAG, "Register cllback called");
			if (cb != null)
				callback = cb;
		}

		@Override
		public boolean isMediaPlayerPlaying() throws RemoteException {
			// TODO Auto-generated method stub
			return mp.isPlaying();
		}

		@Override
		public void syncStatus() throws RemoteException {
			// TODO Auto-generated method stub
			/*
			if (!syncThread.isAlive())
				syncThread.start();
			*/
		}

		@Override
		public void pause() throws RemoteException {
			// TODO Auto-generated method stub
			mp.pause();			
		}

		@Override
		public void play() throws RemoteException {
			// TODO Auto-generated method stub
			mp.start();
			
			notify.icon = R.drawable.delta;
			notify.tickerText = "Playing..";
			notify.when = System.currentTimeMillis();
			
			Intent toLaunch = new Intent(DroolService.this, MediaPlayerActivity.class);
			toLaunch.putExtra(MediaPlayerActivity.TYPE, MediaPlayerActivity.SONG);
			toLaunch.putExtra(MediaPlayerActivity.DATA, Id);
			toLaunch.putExtra(MediaPlayerActivity.DATA1, albumId);
			
			toLaunch.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
			toLaunch.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
			
			PendingIntent intentBack = 
				PendingIntent.getActivity(DroolService.this, 0, toLaunch, PendingIntent.FLAG_CANCEL_CURRENT);
			//notify.setLatestEventInfo(DroolService.this, "Drool", "Playing a song...", intentBack);
			notify.setLatestEventInfo(DroolService.this, "Drool", AlbumName + "/" + SongName, intentBack);
			
			notifier.notify(1, notify);
			
			if (npCallback != null){
				npCallback.mpPlaying();
			}
		}

		@Override
		public void setPosition(int newPosition) throws RemoteException {
			// TODO Auto-generated method stub
			mp.seekTo(newPosition);
		}

		@Override
		public String getAlbumName() throws RemoteException {
			// TODO Auto-generated method stub
			return AlbumName;
		}

		@Override
		public String getArtist() throws RemoteException {
			// TODO Auto-generated method stub
			return Artist;
		}

		@Override
		public String getSongName() throws RemoteException {
			// TODO Auto-generated method stub
			return SongName;
		}

		@Override
		public String getAlbumId() throws RemoteException {
			// TODO Auto-generated method stub
			return albumId;
		}

		@Override
		public void setPlaylistItems(List<String> pl) throws RemoteException {
			// TODO Auto-generated method stub
			Iterator it = playlistItems.listIterator();
			
			while (it.hasNext()){
				it.next();
				it.remove();
			}
			
			it = pl.listIterator();
			
			while (it.hasNext()){
				playlistItems.add((String) it.next());
			}
			
			// test
			/*
			it = playlistItems.listIterator();
			Log.i(TAG, "New playlist ...");
			
			while (it.hasNext()){
				Log.i(TAG, (String) it.next());
			}
			*/
			//test end
		}

		@Override
		public List<String> getPlaylistItems() throws RemoteException {
			// TODO Auto-generated method stub
			return playlistItems;
		}

		@Override
		public void setPlaylistController(String controller)
				throws RemoteException {
			// TODO Auto-generated method stub
			playlistController = controller;
		}

		@Override
		public void setCurrentSongId(int songIndex) throws RemoteException {
			// TODO Auto-generated method stub
			currentSongIndex = songIndex;
		}

		@Override
		public void registerNowPlayingCallback(INowPlayingCallback cb)
				throws RemoteException {
			Log.i(TAG, "Now playing callback registering");
			if (cb != null){
				npCallback = cb;
			}
			
		}

		@Override
		public void setPlaylistLoop(int l) throws RemoteException {
			loopState = l;
			
		}

		@Override
		public void setPlaylistShuffle(int s) throws RemoteException {
			shuffleState = s; 
			
		}
			};

}
